home *** CD-ROM | disk | FTP | other *** search
- unit Logicev;
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, ExtCtrls, VBXCtrl, Switch, StdCtrls, Buttons, TabNotBk,
- Grids, About;
-
- type
- TLogicEval = class(TForm)
- Screens: TTabbedNotebook;
-
- A: TBiSwitch; { Input Switches on EXECUTE form. }
- B: TBiSwitch;
- C: TBiSwitch;
- D: TBiSwitch;
-
- W: TShape; { Four LEDs on EXECUTE form. }
- X: TShape;
- Y: TShape;
- Z: TShape;
- WLbl: TLabel; {Labels on the LEDs. }
- XLbl: TLabel;
- YLbl: TLabel;
- ZLbl: TLabel;
- E: TShape;
- F: TShape;
- G: TShape;
- I: TShape;
- J: TShape;
- H: TShape;
- K: TShape;
- SevenSeg: TPanel;
- ExecVariables: TStringGrid;
-
- EqnList: TListBox; { List of equations on execute page. }
-
- AInit: TGroupBox; { "Buttons" on the INIT page. }
- BInit: TGroupBox;
- CInit: TGroupBox;
- DInit: TGroupBox;
- EInit: TGroupBox;
- FInit: TGroupBox;
- GInit: TGroupBox;
- Hinit: TGroupBox;
- IInit: TGroupBox;
- Jinit: TGroupBox;
- KInit: TGroupBox;
- LInit: TGroupBox;
- MInit: TGroupBox;
- NInit: TGroupBox;
- OInit: TGroupBox;
- PInit: TGroupBox;
- QInit: TGroupBox;
- RInit: TGroupBox;
- SInit: TGroupBox;
- TInit: TGroupBox;
- UInit: TGroupBox;
- VInit: TGroupBox;
- WInit: TGroupBox;
- XInit: TGroupBox;
- YInit: TGroupBox;
- ZInit: TGroupBox;
-
- AValue: TLabel; { Values displayed on the "INIT" page. }
- BValue: TLabel;
- CValue: TLabel;
- DValue: TLabel;
- EValue: TLabel;
- FValue: TLabel;
- GValue: TLabel;
- HValue: TLabel;
- IValue: TLabel;
- JValue: TLabel;
- KValue: TLabel;
- LValue: TLabel;
- MValue: TLabel;
- NValue: TLabel;
- OValue: TLabel;
- PValue: TLabel;
- QValue: TLabel;
- RValue: TLabel;
- SValue: TLabel;
- TValue: TLabel;
- UValue: TLabel;
- VValue: TLabel;
- WValue: TLabel;
- XValue: TLabel;
- YValue: TLabel;
- ZValue: TLabel;
-
-
- Exit: TButton; { Various buttons appearing on the forms. }
- ExitBtn1: TButton;
- ExitBtn: TButton;
- AboutBtn1: TButton;
- AboutBtn2: TButton;
- AboutBtn3: TButton;
- AddEqnBtn: TButton;
- DeleteBtn: TButton;
- EditBtn: TButton;
- PrintBtn: TButton;
- PrintBtn2: TButton;
- PrintBtn3: TButton;
- PulseBtn: TBitBtn;
-
- PrintDialog: TPrintDialog;
- InstabilityAnnunc: TPanel;
-
- tt30: TPanel; { Squares in the truth table on the create page }
- tt31: TPanel;
- tt32: TPanel;
- tt33: TPanel;
- tt00: TPanel;
- tt01: TPanel;
- tt02: TPanel;
- tt03: TPanel;
- tt10: TPanel;
- tt20: TPanel;
- tt11: TPanel;
- tt12: TPanel;
- tt13: TPanel;
- tt21: TPanel;
- tt22: TPanel;
- tt23: TPanel;
-
- ctt00: TPanel;
- ctt10: TPanel;
- ctt20: TPanel;
- ctt30: TPanel;
- ctt01: TPanel;
- ctt02: TPanel;
- ctt03: TPanel;
- ctt11: TPanel;
- ctt12: TPanel;
- ctt13: TPanel;
- ctt21: TPanel;
- ctt22: TPanel;
- ctt23: TPanel;
- ctt31: TPanel;
- ctt32: TPanel;
- ctt33: TPanel;
-
-
- ba00: TLabel; {Labels on the truth table. }
- ba01: TLabel;
- ba10: TLabel;
- ba11: TLabel;
- dc00: TLabel;
- DC01: TLabel;
- DC10: TLabel;
- DC11: TLabel;
- dc211: TLabel;
- dc210: TLabel;
- dc201: TLabel;
- dc200: TLabel;
-
- RBrace1: TLabel;
- ClkLbl1: TLabel;
- RBrace2: TLabel;
- ClkLbl2: TLabel;
-
- InitInstrsLbl: TLabel;
- Instrs2: TLabel;
- ExecEqns: TMemo;
-
- procedure COn(Sender: TObject);
- procedure COff(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure AOff(Sender: TObject);
- procedure AOn(Sender: TObject);
- procedure BOff(Sender: TObject);
- procedure BOn(Sender: TObject);
- procedure DOff(Sender: TObject);
- procedure DOn(Sender: TObject);
- procedure ExitBtnClick(Sender: TObject);
- procedure AboutBtn2Click(Sender: TObject);
- procedure InitClick(Sender: TObject);
- procedure AddEqnBtnClick(Sender: TObject);
- procedure ValueClick(Sender: TObject);
- procedure EqnListClick(Sender: TObject);
- procedure EditBtnClick(Sender: TObject);
- procedure EqnListDblClick(Sender: TObject);
- procedure DeleteBtnClick(Sender: TObject);
- procedure PrintBtnClick(Sender: TObject);
- procedure ScreensChange(Sender: TObject; NewTab: Integer;
- var AllowChange: Boolean);
- procedure PulseBtnClick(Sender: TObject);
-
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
-
-
- { TruthType- Data type that holds the binary information of a truth }
- { table. NumVars is the number of variables that provide }
- { indexes into this truth table. theVars[0..3] are the }
- { single character variable names used in this function. }
- { theVars[4] is where the function stores its result. }
- { tt[clk,d,c,b,a] is the actual truth table. }
-
- TruthType = record
- NumVars:integer;
- theVars:array [0..4] of char;
- tt:array [0..1,0..1,0..1,0..1,0..1] of integer;
-
- end;
- var
- LogicEval: TLogicEval;
-
- { tt is an array of pointers to the panels that make up the squares }
- { of the truth table on the create page. It provides a convenient }
- { way to access those panels using array notation. }
-
- tt: array [0..1, 0..1, 0..1, 0..1, 0..1] of TPanel;
-
- { TruthTbls holds the truth tables for each of the functions the }
- { user defines on the Create page. }
-
- TruthTbls: array ['A'..'Z'] of TruthType;
-
- { EqnSet holds the set of variables that have been defined and for }
- { which truth tables exist. }
-
- EqnSet: set of char;
-
-
-
-
-
-
-
-
-
- implementation
-
- {$R *.DFM}
-
- uses EqnEntry;
-
-
- type
- variables= array ['@'..'['] of integer;
-
- var
-
- { Values holds the current values of all the variables in the system }
- { Values2 is an array of pointers that point at the labels that }
- { display each of the values on the initialization page. }
-
- Values: variables;
- Values2: array ['@'..'['] of TLabel;
-
-
-
-
-
- { FormCreate does all the initialization when the program starts. }
-
- procedure TLogicEval.FormCreate(Sender: TObject);
- var i:integer;
- ch:char;
-
- begin
-
-
- { Label all the variables on the EXECUTE page. Also, set their }
- { values all to zero. }
-
- for i := 1 to 26 do
- begin
-
- ExecVariables.Cells[i,0] := chr(ord('@') + i);
- ExecVariables.Cells[i,1] := '0';
-
- end;
- ExecVariables.Cells[0,0] := '#';
- ExecVariables.Cells[0,1] := '0';
-
- { Initialize all the variable values to zero. }
-
- for ch := '@' to '[' do Values[ch] := 0;
-
- { At this point there are no equations defined. Note that here. }
-
- EqnSet := [];
-
- { Initialize the array of Value pointers so they point at the }
- { value labels on the initialization page. }
-
- Values2['A'] := AValue;
- Values2['B'] := BValue;
- Values2['C'] := CValue;
- Values2['D'] := DValue;
- Values2['E'] := EValue;
- Values2['F'] := FValue;
- Values2['G'] := GValue;
- Values2['H'] := HValue;
- Values2['I'] := IValue;
- Values2['J'] := JValue;
- Values2['K'] := KValue;
- Values2['L'] := LValue;
- Values2['M'] := MValue;
- Values2['N'] := NValue;
- Values2['O'] := OValue;
- Values2['P'] := PValue;
- Values2['Q'] := QValue;
- Values2['R'] := RValue;
- Values2['S'] := SValue;
- Values2['T'] := TValue;
- Values2['U'] := UValue;
- Values2['V'] := VValue;
- Values2['W'] := WValue;
- Values2['X'] := XValue;
- Values2['Y'] := YValue;
- Values2['Z'] := ZValue;
-
-
- { Initialize the tt array so that each element points at the }
- { appropriate square on the truth table on the CREATE page. }
-
- tt[0, 0,0,0,0]:= tt00;
- tt[0, 0,0,0,1]:= tt01;
- tt[0, 0,0,1,0]:= tt02;
- tt[0, 0,0,1,1]:= tt03;
-
- tt[0, 0,1,0,0]:= tt10;
- tt[0, 0,1,0,1]:= tt11;
- tt[0, 0,1,1,0]:= tt12;
- tt[0, 0,1,1,1]:= tt13;
-
- tt[0, 1,0,0,0]:= tt20;
- tt[0, 1,0,0,1]:= tt21;
- tt[0, 1,0,1,0]:= tt22;
- tt[0, 1,0,1,1]:= tt23;
-
- tt[0, 1,1,0,0]:= tt30;
- tt[0, 1,1,0,1]:= tt31;
- tt[0, 1,1,1,0]:= tt32;
- tt[0, 1,1,1,1]:= tt33;
-
-
- tt[1, 0,0,0,0]:= ctt00;
- tt[1, 0,0,0,1]:= ctt01;
- tt[1, 0,0,1,0]:= ctt02;
- tt[1, 0,0,1,1]:= ctt03;
-
- tt[1, 0,1,0,0]:= ctt10;
- tt[1, 0,1,0,1]:= ctt11;
- tt[1, 0,1,1,0]:= ctt12;
- tt[1, 0,1,1,1]:= ctt13;
-
- tt[1, 1,0,0,0]:= ctt20;
- tt[1, 1,0,0,1]:= ctt21;
- tt[1, 1,0,1,0]:= ctt22;
- tt[1, 1,0,1,1]:= ctt23;
-
- tt[1, 1,1,0,0]:= ctt30;
- tt[1, 1,1,0,1]:= ctt31;
- tt[1, 1,1,1,0]:= ctt32;
- tt[1, 1,1,1,1]:= ctt33;
-
- { Initialize the default equation for the equation editor. }
-
- LastEqn := 'F=0';
-
- { Make the CREATE page show up on the form when we start. }
-
- Screens.ActivePage := 'Create';
-
- end;
-
-
-
- { The following procedure stores "Value" into the variable specified by }
- { "vName". It also updates the variable display and any necessary LEDs }
- { on the EXECUTE page. }
-
- procedure SetVar(vName:char; Value:integer);
- begin
-
- with LogicEval do begin
-
- { Convert "#" to "@" so we can use a compact array ("@" appears }
- { just before "A" in the ASCII character set, "#" is some distance }
- { away from the alphabetic characters). }
-
- if (vName = '#') then vName := '@';
-
- { Update the value in the Values matrix and the label on the init- }
- { ialization page. }
-
- Values [vName] := Value;
- Values2[vName].Caption := chr(Value+ord('0'));
-
- { Update the value on the EXECUTE page. }
-
- ExecVariables.Cells[ord(vName)-ord('@'),1] :=
- chr(ord('0') + Value);
-
- { If this variable is E..K, then update the corresponding segment }
- { on the seven-segment display. }
-
- if (vName = 'E') then
- if (Value = 1) then E.Brush.Color := clRed
- else E.Brush.Color := clSilver;
-
- if (vName = 'F') then
- if (Value = 1) then F.Brush.Color := clRed
- else F.Brush.Color := clSilver;
-
- if (vName = 'G') then
- if (Value = 1) then G.Brush.Color := clRed
- else G.Brush.Color := clSilver;
-
- if (vName = 'H') then
- if (Value = 1) then H.Brush.Color := clRed
- else H.Brush.Color := clSilver;
-
- if (vName = 'I') then
- if (Value = 1) then I.Brush.Color := clRed
- else I.Brush.Color := clSilver;
-
- if (vName = 'J') then
- if (Value = 1) then J.Brush.Color := clRed
- else J.Brush.Color := clSilver;
-
- if (vName = 'K') then
- if (Value = 1) then K.Brush.Color := clRed
- else K.Brush.Color := clSilver;
-
-
- { If this variable is W..Z, then update the corresponding LED. }
-
- if (vName = 'W') then
- if (Value = 1) then W.Brush.Color := clRed
- else W.Brush.Color := clWhite;
-
- if (vName = 'X') then
- if (Value = 1) then X.Brush.Color := clRed
- else X.Brush.Color := clWhite;
-
- if (vName = 'Y') then
- if (Value = 1) then Y.Brush.Color := clRed
- else Y.Brush.Color := clWhite;
-
- if (vName = 'Z') then
- if (Value = 1) then Z.Brush.Color := clRed
- else Z.Brush.Color := clWhite;
-
- end;
- end;
-
-
-
-
- { The following function evaluates the system of logic equations. }
-
- procedure Eval;
- var
- i :integer;
- funcCount :integer;
- CurVar :char;
- prevVals :variables;
-
-
-
- { CmpVars- Compares two arrays of type "variables" and returns }
- { true if they are equal. }
-
- function CmpVars(var v1, v2:Variables):boolean;
- assembler;
- asm
- push ds
- les di, v2
- lds si, v1
- mov cx, 27
- repe cmpsw
- mov ax, 1
- cmp cx, 0
- je @@0
- mov ax, 0
- @@0:
- pop ds
- end;
-
-
- { EvalOnce- Evaluates all the active logic equations one time each. }
- { This function returns the number of active logic equa- }
- { tions in the system. Note that for a complete logic }
- { system evaluation, that is, to allow values to propogate}
- { throughout the system of equations, you must evaluate }
- { the set of equations at least n times where "n" is the }
- { number of logic equations in the system. }
-
- function EvalOnce:integer;
- var
- funcName: char;
- val: integer;
-
- begin
-
- Result := 0;
-
- { The following loop, in conjunction with the IF stmt, executes once }
- { for each active equation in the system. }
-
- for funcName := 'A' to 'Z' do
- if funcName in EqnSet then
- begin
-
- { The following case statement handles the case where the current }
- { equation has zero, one, two, three, or four variables. It com- }
- { putes the new value by using a lookup based on the current vari-}
- { able values. }
-
- case TruthTbls[funcName].NumVars of
- 0: val := TruthTbls[funcName].tt[Values['@'],0,0,0,0];
- 1: val := TruthTbls[funcName].tt[Values['@'],0,0,0,
- Values[TruthTbls[funcName].theVars[0]]];
- 2: val := TruthTbls[funcName].tt[Values['@'],0,0,
- Values[TruthTbls[funcName].theVars[1]],
- Values[TruthTbls[funcName].theVars[0]]];
- 3: val := TruthTbls[funcName].tt[Values['@'],0,
- Values[TruthTbls[funcName].theVars[2]],
- Values[TruthTbls[funcName].theVars[1]],
- Values[TruthTbls[funcName].theVars[0]]];
- 4: val := TruthTbls[funcName].tt[Values['@'],
- Values[TruthTbls[funcName].theVars[3]],
- Values[TruthTbls[funcName].theVars[2]],
- Values[TruthTbls[funcName].theVars[1]],
- Values[TruthTbls[funcName].theVars[0]]];
- end;
-
- { Update the current function's variable with the value obtained above. }
-
- Values[funcName] := val;
-
- { Count the number of functions we've processed down here. }
-
- inc(Result);
-
- end;
- end;
-
-
-
-
- begin {Eval}
-
- { Call EvalOnce to obtain the number of functions in the system. }
- { Bump this value by one since we've got the clock variable to worry}
- { about, as well. }
-
- funcCount := EvalOnce + 1;
-
-
- { Evaluate the system of equations "funcCount" times. This gives }
- { us a total of "n+2" evaluations where "n" is the number of funcs. }
- { The first extra execution is for the clock variable, the second }
- { extra execution provides a safety margin. }
-
- for i := 1 to funcCount do EvalOnce;
-
- { Now let's check for instability. Save the current set of values }
- { and execute the set of equations one more time. If the system is }
- { stable, we should obtain the exact same set of values. If the }
- { system is unstable, they will differ. }
-
- prevVals := Values;
- EvalOnce;
-
- { If the system is unstable, turn on the Instability annunciator. }
- { If the system is stable, turn the annunciator off. }
-
- if CmpVars(prevVals,Values) then
- LogicEval.InstabilityAnnunc.Color := clGray
- else LogicEval.InstabilityAnnunc.Color := clRed;
-
- { Throughout the operations above, EvalOnce stored results directly }
- { into the Values array rather than (correctly) calling SetVar. The }
- { reason is because EvalOnce would call SetVar a tremendous number }
- { of times and SetVar is rather slow. Therefore, we need to call }
- { SetVar once for each variable to ensure that all LEDs, display }
- { values, etc., are properly updated. }
-
- for CurVar := '@' to 'Z' do
- SetVar(CurVar,Values[CurVar]);
-
- end;
-
-
-
-
-
-
- { The following procedures handle button toggle events. Whenever the }
- { user toggles one of the four input values (A..D) the following pro- }
- { cedures adjust the values of the corresponding variables and then }
- { they evaluate the system of logic equations. }
-
- procedure TLogicEval.AOff(Sender: TObject);
- begin
- SetVar('A',0);
- Eval;
- end;
-
- procedure TLogicEval.AOn(Sender: TObject);
- begin
- SetVar('A',1);
- Eval;
- end;
-
- procedure TLogicEval.BOff(Sender: TObject);
- begin
- SetVar('B',0);
- Eval;
- end;
-
- procedure TLogicEval.BOn(Sender: TObject);
- begin
- SetVar('B',1);
- Eval;
- end;
-
- procedure TLogicEval.COn(Sender: TObject);
- begin
- SetVar('C',1);
- Eval;
- end;
-
- procedure TLogicEval.COff(Sender: TObject);
- begin
- SetVar('C',0);
- Eval;
- end;
-
- procedure TLogicEval.DOff(Sender: TObject);
- begin
- SetVar('D',0);
- Eval;
- end;
-
- procedure TLogicEval.DOn(Sender: TObject);
- begin
- SetVar('D',1);
- Eval;
- end;
-
-
- { If the user hits the "Pulse" button, set the clock to zero and eval- }
- { uate the system, set the clock to one and evaluate the system, and }
- { then set the clock back to zero and reevaluate the equations. }
-
- procedure TLogicEval.PulseBtnClick(Sender: TObject);
- begin
-
- Values['@'] := 0;
- Eval;
- Values['@'] := 1;
- Eval;
- Values['@'] := 0;
- Eval;
-
- end;
-
-
- { The system calls the following functions whenever the user clicks on }
- { one of the buttons on the initialization page. This code figures }
- { out which button was pressed and toggles its value. The InitClick }
- { procedure runs whenever the user clicks on the panel (button), the }
- { ValueClick procedure runs if the users clicks on the actual value }
- { within the panel. }
-
- procedure TLogicEval.InitClick(Sender: TObject);
- var name:char;
- begin
-
- {The first character of the Box's Caption is the variable's name. }
-
- name := (Sender as TGroupBox).Caption[1];
-
- { Fetch that variable's value, invert it, and write it back. }
-
- SetVar(Name, Values[name] xor 1);
-
- end;
-
- procedure TLogicEval.ValueClick(Sender: TObject);
- var name:char;
- begin
-
- name := ((Sender as TLabel).Parent as TGroupBox).Caption[1];
- SetVar(Name, Values[name] xor 1);
-
- end;
-
-
-
-
- { If the user presses the "ADD" button, bring up the equation dialog }
- { box and let them add a new equation to the system. }
-
- procedure TLogicEval.AddEqnBtnClick(Sender: TObject);
- begin
-
- EqnDlg.InputEqn.SelectAll; {Select equation inside dialog box. }
- EqnDlg.Show; {Open the equation dialog box. }
-
- end;
-
-
- { If the user clicks on an equation in the equation list box, update }
- { the truth table on the create page to display the truth table for }
- { the selected equation. }
-
- procedure TLogicEval.EqnListClick(Sender: TObject);
- var ch:char;
- begin
-
- if (EqnList.ItemIndex <> -1) then {Make sure there is a selection. }
- begin
-
- ch := EqnList.Items[EqnList.ItemIndex][1]; {Get function name. }
- DrawTruths(TruthTbls[ch]); {Draw that function's truth table. }
-
- end;
-
- end;
-
-
- { If the user double-clicks on an equation in the equation list box, }
- { then bring up the equation editor dialog box and let them edit this }
- { equation. }
-
- procedure TLogicEval.EqnListDblClick(Sender: TObject);
- begin
-
- if (EqnList.ItemIndex <> -1) then {Is there a selection? }
- begin
-
- { Grab the equation the user just selected and make it the }
- { default equation in the equation dialog box. }
-
- EqnDlg.InputEqn.Text := EqnList.Items[EqnList.ItemIndex];
-
- { Select the equation. }
-
- EqnDlg.InputEqn.SelectAll;
-
- { Bring up the equation editor dialog box. }
-
- EqnDlg.Show;
-
- end;
- end;
-
-
- { If the user presses the edit button and there is a selected equation }
- { in the equation list box, open up the equation editor dialog box and }
- { let the user edit that equation. }
-
- procedure TLogicEval.EditBtnClick(Sender: TObject);
- begin
-
- { If there is a selected equation, copy it to the default }
- { equation in the equation editor dialog box. If there is no }
- { such equation available, just use the current default equa- }
- { tion when it opens the equation editor dialog box. }
-
- if (EqnList.Items.Count <> 0) then {Are there any equations? }
- if (EqnList.ItemIndex <> -1) then {Is an equation selected? }
- EqnDlg.InputEqn.Text := EqnList.Items[EqnList.ItemIndex];
-
- { Select the equation and open up the dialog box. }
-
- EqnDlg.InputEqn.SelectAll;
- EqnDlg.Show;
-
- end;
-
-
- { If the user has selected and equation and presses the delete button, }
- { the following procedure deletes that equation from the list and re- }
- { moves that function definition from the EqnSet. }
-
- procedure TLogicEval.DeleteBtnClick(Sender: TObject);
- var ch: char;
- dummy: TruthType;
- begin
-
- if (EqnList.ItemIndex <> -1) then {Is there an equation selected? }
- begin
-
- { Make sure the user really wants to do this. }
-
- if MessageDlg('Okay to delete ' +
- EqnList.Items[EqnList.ItemIndex] + '?',
- mtWarning, [mbYes, mbNo], 0) = mrYes then
- begin
-
- { Remove the equation from our equation set. }
-
- EqnSet := EqnSet - [EqnList.Items[EqnList.ItemIndex][1]];
-
- { Remove the equation from the list of equations. }
-
- EqnList.Items.Delete(EqnList.ItemIndex);
-
- { Since there is no longer a selected equation in the }
- { equation list, clear the truth tables. }
-
- dummy.NumVars := 0;
- DrawTruths(dummy);
-
- end;
-
- end;
- end;
-
-
- { Miscellaneous procedures to handle the PRINT, ABOUT, and EXIT buttons }
- { found on each page of the form. }
-
- procedure TLogicEval.PrintBtnClick(Sender: TObject);
- begin
-
- if (PrintDialog.Execute) then
- begin
-
- LogicEval.Print;
-
- end;
-
- end;
-
- procedure TLogicEval.ExitBtnClick(Sender: TObject);
- begin
- Halt;
- end;
-
- procedure TLogicEval.AboutBtn2Click(Sender: TObject);
- begin
- AboutBox.Show;
- end;
-
-
- procedure TLogicEval.ScreensChange( Sender: TObject;
- NewTab: Integer;
- var AllowChange: Boolean);
- var
- i: integer;
- begin
-
- AllowChange := true;
- if NewTab = 2 then
- begin
-
- ExecEqns.Clear;
- for i := 0 to EqnList.Items.Count - 1 do
- ExecEqns.Lines.Add(EqnList.Items[i]);
-
- Eval;
-
- end;
- end;
-
- end.
-